package com.dzjcloud.dzj.upms.biz.controller;


import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Validator;
import com.dzjcloud.dzj.common.core.enums.ResultEnum;
import com.dzjcloud.dzj.common.core.utils.HttpUtils;
import com.dzjcloud.dzj.common.core.utils.R;
import com.dzjcloud.dzj.common.minio.service.MinioTemplate;
import com.dzjcloud.dzj.common.minio.utils.BucketUtils;
import com.dzjcloud.dzj.upms.biz.service.FileService;
import com.dzjcloud.dzj.upms.biz.utils.MinioURLUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.Map;

/**
 * <h3>pig</h3>
 * <p>文件前端控制器</p>
 *
 * @author : DongZeJian
 * @date : 2020-12-31 15:44
 **/
@RestController
@RequiredArgsConstructor
@RequestMapping("/file")
@Api(value = "file", tags = "文件前端控制器")
@Slf4j
public class FileController {

	private final MinioTemplate minioTemplate;

	@Autowired
	private MinioURLUtils minioURLUtils;

	@Autowired
	private FileService fileService;

	/**
	 * 单文件上传
	 *
	 * @param file       文件名称
	 * @param uploadType 系统模块 1:upms、2二手房网签
	 * @return
	 */
	@ApiOperation(value = "上传单文件到资源中心", notes = "上传单文件到资源中心", produces = "application/json")
	@PostMapping(value = "/uploadFileToCenter")
	public R<Map<String,String>> uploadFileToCenter(@ApiParam(value = "文件", required = true) @RequestParam("file") MultipartFile file,
								@ApiParam(value = "系统模块 1:upms、2:question", required = true) @RequestParam("uploadType") Integer uploadType) {
		return R.ok(fileService.uploadFileToCenter(file,uploadType));
	}

	/**
	 * 获取文件的URL访问地址
	 *
	 * @param fileName   文件名
	 * @param uploadType 系统模块 1:upms
	 * @return
	 */
	@ApiOperation(value = "获取文件的URL访问地址", notes = "获取文件的URL访问地址", produces = "application/json")
	@PostMapping("/getObjectURL")
	public R<String> getObjectURL(@ApiParam(value = "访问文件名", required = true)@NotBlank(message = "文件名称不能为空") @RequestParam String fileName,
                                  @ApiParam(value = "1:upms、2:question", required = true)@NotNull(message = "系统模块不能为空") @RequestParam Integer uploadType,
                                  @ApiParam(value = "是否永久链接", required = true)@NotNull(message = "请选择是否要永久链接") @RequestParam Boolean permanentLink) {

		//获取bucketName 判断bucketName是否为后台指定
		String bucketName = Validator.validateNotEmpty(BucketUtils.getValue(uploadType), ResultEnum.PARAM_IS_ERROR.getMessage());

		//判断是否要永久链接
		if (permanentLink){
			return R.ok(minioURLUtils.getMinioURl(fileName,uploadType));
		}
		//返回为期7天的链接
		return R.ok(minioTemplate.getObjectURL(bucketName, fileName, 7 * 24 * 60 * 60));
	}

	/**
	 * 获取文件
	 *
	 * @param fileName 文件空间/名称
	 * @param response
	 * @return
	 */
	@SneakyThrows
	@ApiOperation(value = "获取文件", notes = "获取文件", produces = "application/json")
	@GetMapping("/{fileName}/{uploadType}")
	public void file(@ApiParam(value = "访问文件名", required = true) @PathVariable(value = "fileName") String fileName,
                     @ApiParam(value = "系统模块 1:upms、2:question", required = true) @PathVariable(value = "uploadType") Integer uploadType, HttpServletResponse response) throws IOException {
		//获取bucketName 判断bucketName是否为后台指定
		String bucketName = Validator.validateNotEmpty(BucketUtils.getValue(uploadType), ResultEnum.PARAM_IS_ERROR.getMessage());

		try (java.io.InputStream inputStream = minioTemplate.getObject(bucketName, fileName)) {
			response.setContentType("application/octet-stream; charset=UTF-8");
			response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
			IoUtil.copy(inputStream, response.getOutputStream());
		} catch (Exception e) {
			log.error("文件读取异常: {}", ExceptionUtil.stacktraceToString(e));
			HttpUtils.writeError(response, "文件读取异常");
			return;
		}
	}

	/**
	 * 删除资源中心文件
	 *
	 * @param fileName   文件名称
	 * @param uploadType 系统模块 1:upms
	 * @return
	 */
	@ApiOperation(value = "文件删除")
	@GetMapping("/deletefile/{fileName}/{uploadType}")
	public R<Boolean> deletefile(@ApiParam(value = "文件名称", required = true) @PathVariable(value = "fileName") String fileName,
                                 @ApiParam(value = "系统模块 1:upms、2:question", required = true) @PathVariable(value = "uploadType") Integer uploadType) {
		return R.ok(fileService.deletefile(fileName,uploadType));
	}

	/**
	 * 内部调用获取URL
	 */
	@GetMapping("/internalGetUrl/{fileName}/{uploadType}")
	public R<String> internalGetUrl(@PathVariable String fileName, @PathVariable Integer uploadType){
		return R.ok(minioURLUtils.getMinioURl(fileName,uploadType));
	}
}
